/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.xwc.example.tab;

import com.github.xwc.example.ResourceTable;
import com.github.xwc.view.AttrUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.PageSlider;
import ohos.agp.components.PageSliderProvider;
import ohos.agp.components.ScrollView;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * DynamicPagerIndicator
 *
 * @since 2021-03-04
 */
public class DynamicPagerIndicator extends DependentLayout implements PageSlider.PageChangedListener {
    /**
     * 指示器的模式：可滑动的
     */
    public static final int INDICATOR_MODE_SCROLLABLE = 1;

    /**
     * 指示器的模式：不可滑动的，且均分
     */
    public static final int INDICATOR_MODE_FIXED = 2;

    /**
     * 指示器的模式：不可滑动，居中模式
     */
    public static final int INDICATOR_MODE_SCROLLABLE_CENTER = 3;

    /**
     * 滑动条的滚动的模式：动态变化模式（Indicator长度动态变化）
     */
    public static final int INDICATOR_SCROLL_MODE_DYNAMIC = 1;

    /**
     * 滑动条的滚动的模式：固定长度的移动模式（Indicator长度不变，移动位置变化）
     */
    public static final int INDICATOR_SCROLL_MODE_TRANSFORM = 2;

    /**
     * tab view的文字颜色变化模式  TAB_TEXT_COLOR_MODE_COMMON，普通模式
     */
    public static final int TAB_TEXT_COLOR_MODE_COMMON = 1;

    /**
     * tab view的文字颜色变化模式  TAB_TEXT_COLOR_MODE_GRADIENT，渐变模式
     */
    public static final int TAB_TEXT_COLOR_MODE_GRADIENT = 2;

    /**
     * tab view的文字字体变化模式  TAB_TEXT_SIZE_MODE_COMMON，普通模式
     */
    public static final int TAB_TEXT_SIZE_MODE_COMMON = 1;

    /**
     * tab view的文字字体变化模式  TAB_TEXT_SIZE_MODE_GRADIENT，渐变模式
     */
    public static final int TAB_TEXT_SIZE_MODE_GRADIENT = 2;

    /**
     * 指示器滑动到居中位置的方式，PAGER_INDICATOR_SCROLL_MODE_SYNC ，联动模式，跟随页面一起移动到居中位置
     */
    public static final int PAGER_INDICATOR_SCROLL_TO_CENTER_MODE_LINKAGE = 1;
    /**
     * 指示器滑动到居中位置的方式，PAGER_INDICATOR_SCROLL_MODE_SYNC ，异动模式，等页面滑动完成，再将对应的TabView移动到居中位置
     */
    public static final int PAGER_INDICATOR_SCROLL_TO_CENTER_MODE_TRANSACTION = 2;

    private static final float VALUE_HALF = 0.5f;

    private static final int DEFAULT_TABPADDING = 16;

    private static final int DEFAULT_TABNORMALTEXTSIZE = 18;

    private static final int DEFAULT_TABSELECTEDTEXTSIZE = 18;

    private static final int DEFAULT_INDICATORLINEHEIGHT = 4;

    private static final int DEFAULT_INDICATORLINEWIDTH = 30;

    private static final int DEFAULT_INDICATORLINEMARGINTOP = 5;

    private static final int DEFAULT_INDICATORLINEMARGINBOTTOM = 5;

    private static final int DEFAULT_LINE_WIDTH = 25;

    private static final float VALUE_TWO = 2.0f;

    /**
     * Context
     */
    protected Context mContext;

    /**
     * 即整个指示器控件的显示模式,共有三种模式,默认为INDICATOR_MODE_FIXED
     */
    private int mPagerIndicatorMode;

    /**
     * 即指示器的滚动模式，该模式只有当mPagerIndicatorMode = INDICATOR_MODE_SCROLLABLE有效。
     * 共有两种，第一种是滑动页面时，整个导航栏同步移动到居中的位置，用PAGER_INDICATOR_SCROLL_MODE_SYNC标识
     * 第一种是滑动页面完整后，才将需要居中显示的栏目滑动的居中的位置。用PAGER_INDICATOR_SCROLL_MODE_ASYNC标识
     */
    private int mPagerIndicatorScrollToCenterMode;

    /**
     * tab的padding,内边距,默认30px
     */
    private int mTabPadding;

    private int mTabPaddingTop;

    private int mTabPaddingBottom;

    private int mCurrentPosition = 0;

    /**
     * tab的正常的字体大小
     */
    private float mTabNormalTextSize;

    /**
     * tab的选中后的字体大小
     */
    private float mTabSelectedTextSize;

    /**
     * tab的正常字体颜色
     */
    private int mTabNormalTextColor;

    /**
     * tab的选中的字体颜色
     */
    private int mTabSelectedTextColor;

    /**
     * tab的正常字体是否加粗
     */
    private boolean isTabNormalTextBold;

    /**
     * tab的选中的字体是否加粗
     */
    private boolean isTabSelectedTextBold;

    /**
     * tab size是否渐变
     */
    private int mTabTextSizeMode;

    /**
     * 指示条移动的模式，共两种，默认INDICATOR_SCROLL_MODE_DYNAMIC
     */
    private int mIndicatorLineScrollMode;

    /**
     * 导航条的高度，默认12px
     */
    private int mIndicatorLineHeight;

    /**
     * 指示条的宽度，默认为60px
     */
    private int mIndicatorLineWidth;

    /**
     * 指示条的是否为圆角，0为不绘制圆角。默认为0
     */
    private float mIndicatorLineRadius;

    /**
     * 指示条变化的起始点颜色
     */
    private int mIndicatorLineStartColor;

    /**
     * 指示条变化的结束点颜色
     */
    private int mIndicatorLineEndColor;

    /**
     * 指示条上边距
     */
    private int mIndicatorLineMarginTop;

    /**
     * 指示条下边距
     */
    private int mIndicatorLineMarginBottom;

    /**
     * TabView的父控件
     */
    private DirectionalLayout mTabParentView;

    /**
     * 指示条
     */
    private ScrollableLine mScrollableLine;

    private PageSlider mViewPager;

    /**
     * INDICATOR_MODE_SCROLLABLE模式下的水平滑动条
     */
    private ScrollView mAutoScrollHorizontalScrollView;

    /**
     * DynamicPagerIndicator
     *
     * @param context context
     */
    public DynamicPagerIndicator(Context context) {
        super(context);
    }

    /**
     * DynamicPagerIndicator
     *
     * @param context context
     * @param attrs attrs
     */
    public DynamicPagerIndicator(Context context, AttrSet attrs) {
        super(context, attrs);
        initDynamicPagerIndicator(context, attrs);
    }

    /**
     * DynamicPagerIndicator
     *
     * @param context context
     * @param attrs attrs
     * @param defStyleAttr def style attr
     */
    public DynamicPagerIndicator(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initDynamicPagerIndicator(context, attrs);
    }

    private void initDynamicPagerIndicator(Context context, AttrSet attributeSet) {
        this.mContext = context;

        mTabPadding = AttrUtil.getDimension(attributeSet, "tabPadding", DEFAULT_TABPADDING);
        mTabPaddingBottom = AttrUtil.getDimension(attributeSet, "tabPaddingBottom", 0);
        mTabPaddingTop = AttrUtil.getDimension(attributeSet, "tabPaddingTop", 0);
        mTabNormalTextColor = AttrUtil.getColorValue(attributeSet, "tabNormalTextColor", "#707070").getValue();
        mTabSelectedTextColor = AttrUtil.getColorValue(attributeSet, "tabSelectedTextColor", "#222230").getValue();
        isTabNormalTextBold = AttrUtil.getBooleanValue(attributeSet, "isTabNormalTextBold", false);
        isTabSelectedTextBold = AttrUtil.getBooleanValue(attributeSet, "isTabSelectedTextBold", false);
        mTabNormalTextSize = AttrUtil.getDimension(attributeSet, "tabNormalTextSize", DEFAULT_TABNORMALTEXTSIZE);
        mTabSelectedTextSize = AttrUtil.getDimension(attributeSet, "tabSelectedTextSize", DEFAULT_TABSELECTEDTEXTSIZE);
        mIndicatorLineHeight = AttrUtil.getDimension(attributeSet, "indicatorLineHeight", DEFAULT_INDICATORLINEHEIGHT);
        mIndicatorLineWidth = AttrUtil.getDimension(attributeSet, "indicatorLineWidth", DEFAULT_INDICATORLINEWIDTH);
        mIndicatorLineRadius = AttrUtil.getDimension(attributeSet, "indicatorLineRadius", 0);
        mIndicatorLineScrollMode = AttrUtil.getIntegerValue(attributeSet, "indicatorLineScrollMode",
                INDICATOR_SCROLL_MODE_DYNAMIC);
        mIndicatorLineStartColor =
                AttrUtil.getColorValue(attributeSet, "indicatorLineStartColor", "#ffffff").getValue();
        mIndicatorLineEndColor = AttrUtil.getColorValue(attributeSet, "indicatorLineEndColor", "#ff00ff").getValue();
        mIndicatorLineMarginTop = AttrUtil.getDimension(attributeSet, "indicatorLineMarginTop",
                DEFAULT_INDICATORLINEMARGINTOP);
        mIndicatorLineMarginBottom = AttrUtil.getDimension(attributeSet, "indicatorLineMarginBottom",
                DEFAULT_INDICATORLINEMARGINBOTTOM);
        mPagerIndicatorMode = AttrUtil.getIntegerValue(attributeSet, "pagerIndicatorMode", INDICATOR_MODE_FIXED);
        mPagerIndicatorScrollToCenterMode = AttrUtil.getIntegerValue(attributeSet, "pagerIndicatorScrollToCenterMode",
                PAGER_INDICATOR_SCROLL_TO_CENTER_MODE_LINKAGE);
        mTabTextSizeMode =
                (mTabNormalTextSize == mTabSelectedTextSize) ? TAB_TEXT_SIZE_MODE_COMMON : TAB_TEXT_SIZE_MODE_GRADIENT;
    }

    private void transformScrollIndicator(int position, float positionOffset) {
        if (mTabParentView != null) {
            Component positionView = mTabParentView.getComponentAt(position);
            int positionLeft = positionView.getLeft();
            int positionViewWidth = positionView.getWidth();
            Component afterView = mTabParentView.getComponentAt(position + 1);
            int afterViewWith = 0;
            if (afterView != null) {
                afterViewWith = afterView.getWidth();
            }
            float startX =
                    positionOffset * (positionViewWidth - ((positionViewWidth - mIndicatorLineWidth) >> 1)
                            + ((afterViewWith - mIndicatorLineWidth) >> 1))
                            + (positionViewWidth - mIndicatorLineWidth) / VALUE_TWO + positionLeft;
            float endX =
                    positionOffset * ((positionViewWidth - mIndicatorLineWidth) / VALUE_TWO
                            + (afterViewWith - (afterViewWith - mIndicatorLineWidth) / VALUE_TWO))
                            + (positionView.getRight() - ((positionViewWidth - mIndicatorLineWidth) >> 1));
            mScrollableLine.updateScrollLineWidth(startX, endX, mIndicatorLineStartColor, mIndicatorLineStartColor,
                    positionOffset);
        }
    }

    /**
     * get pager tab view
     *
     * @param position position
     * @return BasePagerTabView
     */
    public BasePagerTabView getPagerTabView(int position) {
        if (mTabParentView != null && position < mTabParentView.getChildCount()) {
            return (BasePagerTabView) mTabParentView.getComponentAt(position);
        }
        return (BasePagerTabView) mTabParentView;
    }

    /**
     * set scroll line
     */
    public void setScrollLine() {
        mScrollableLine.updateScrollLineWidth(0,
                mIndicatorLineWidth,
                mIndicatorLineStartColor, mIndicatorLineStartColor, 0);
    }

    private void dynamicScrollIndicator(int position, float positionOffset) {
        if (mTabParentView != null && position < mTabParentView.getChildCount()) {
            Component positionView = mTabParentView.getComponentAt(position);
            int positionLeft = 0;
            int positionRight = 0;
            int positionViewWidth = 0;
            if (positionView instanceof BasePagerTabView) {
                positionRight = positionView.getRight();
                positionLeft = positionView.getLeft();
                positionViewWidth = positionView.getWidth();
            }
            Component afterView = mTabParentView.getComponentAt(position + 1);
            int afterViewWith = 0;
            if (afterView != null) {
                afterViewWith = afterView.getWidth();
            }
            if (positionOffset <= VALUE_HALF) {
                float startX = (positionViewWidth - mIndicatorLineWidth) / VALUE_TWO + positionLeft;
                float endX =
                        (VALUE_TWO * positionOffset) * ((positionViewWidth - mIndicatorLineWidth) / VALUE_TWO
                                + (afterViewWith - (afterViewWith - mIndicatorLineWidth) / VALUE_TWO))
                                + (positionRight - ((positionViewWidth - mIndicatorLineWidth) >> 1));
                mScrollableLine.updateScrollLineWidth(startX, endX, mIndicatorLineStartColor, mIndicatorLineEndColor,
                        positionOffset);
            } else {
                float startX =
                        positionLeft + ((positionViewWidth - mIndicatorLineWidth) >> 1)
                                + (float) (positionOffset - VALUE_HALF)
                                * VALUE_TWO * (positionViewWidth - ((positionViewWidth - mIndicatorLineWidth) >> 1)
                                + ((afterViewWith - mIndicatorLineWidth) >> 1));
                float endX = afterViewWith + positionRight - (afterViewWith - mIndicatorLineWidth) / VALUE_TWO;
                mScrollableLine.updateScrollLineWidth(startX, endX, mIndicatorLineEndColor, mIndicatorLineStartColor,
                        positionOffset);
            }
        }
    }

    private void tabTitleColorGradient(int position, float positionOffset) {
        if (mTabParentView != null && position < mTabParentView.getChildCount()) {
            BasePagerTabView basePagerTabView = (BasePagerTabView) mTabParentView.getComponentAt(position);
            if (basePagerTabView != null) {
                int color = TabUtils.evaluateColor(mTabSelectedTextColor, mTabNormalTextColor, positionOffset);
                basePagerTabView.getTabTextView().setTextColor(new Color(color));
            }
            BasePagerTabView afterPageTabView = (BasePagerTabView) mTabParentView.getComponentAt(position + 1);
            if (afterPageTabView != null) {
                int color = TabUtils.evaluateColor(mTabNormalTextColor, mTabSelectedTextColor, positionOffset);
                afterPageTabView.getTabTextView().setTextColor(new Color(color));
            }
        }
    }

    private void tabTitleSizeGradient(int position, float positionOffset) {
        if (mTabParentView != null && position < mTabParentView.getChildCount()) {
            BasePagerTabView basePagerTabView = (BasePagerTabView) mTabParentView.getComponentAt(position);
            if (basePagerTabView != null) {
                int textSize =
                        (int) (mTabSelectedTextSize - (Math.abs(mTabSelectedTextSize - mTabNormalTextSize)
                                * positionOffset));
                basePagerTabView.getTabTextView().setTextSize(textSize);
            }
            BasePagerTabView afterPageTabView = (BasePagerTabView) mTabParentView.getComponentAt(position + 1);
            if (afterPageTabView != null) {
                int textSize =
                        (int) (Math.abs(mTabSelectedTextSize - mTabNormalTextSize) * positionOffset
                                + mTabNormalTextSize);
                afterPageTabView.getTabTextView().setTextSize(textSize);
            }
        }
    }

    @Override
    public void invalidate() {
        super.invalidate();
    }

    private float floatToSubtract(float f1, float f2) {
        BigDecimal b1 = BigDecimal.valueOf(f1);
        BigDecimal b2 = BigDecimal.valueOf(f2);
        DecimalFormat df = new DecimalFormat("0.00000");
        return Float.valueOf(df.format(b1.subtract(b2)));
    }

    @Override
    public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
        DecimalFormat df = new DecimalFormat("0.00000");
        float newPositionOffset = Float.valueOf(df.format(positionOffset));
        int newPosition = position;
        if (positionOffsetPixels > 0) {
            newPositionOffset = positionOffset;
        } else {
            newPositionOffset = floatToSubtract(1f, positionOffset);
            newPosition = position - 1 > 0 ? position - 1 : 0;
        }
        if (mCurrentPosition == position) {
            setScrollTitle(newPosition, newPositionOffset);
        }
    }

    private void setScrollTitle(int position, float positionOffset) {
        if (mIndicatorLineScrollMode == INDICATOR_SCROLL_MODE_DYNAMIC) {
            dynamicScrollIndicator(position, positionOffset);
        } else {
            transformScrollIndicator(position, positionOffset);
        }

        if (mTabTextSizeMode == TAB_TEXT_SIZE_MODE_GRADIENT) {
            tabTitleSizeGradient(position, positionOffset);
        }

        if (mCurrentPosition == position && positionOffset == 0) {
            updateTitleStyle(position);
        }

        if (mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE
                && mPagerIndicatorScrollToCenterMode == PAGER_INDICATOR_SCROLL_TO_CENTER_MODE_LINKAGE) {
            linkageScrollTitleParentToCenter(position, positionOffset);
        }
    }

    @Override
    public void onPageChosen(int position) {
        this.mCurrentPosition = position;
        updateTitleStyle(position);
        setScrollTitle(position, 0);
    }

    @Override
    public void onPageSlideStateChanged(int position) {
        setScrollTitle(mCurrentPosition, 0);
    }

    /**
     * set view pager
     *
     * @param viewPager view pager
     */
    public void setViewPager(PageSlider viewPager) {
        if (viewPager == null || viewPager.getProvider() == null) {
            return;
        }
        this.mViewPager = viewPager;
        updateIndicator(false);
        if (mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE) {
            DependentLayout relativeLayout = new DependentLayout(mContext);
            relativeLayout.setLayoutConfig(new LayoutConfig(LayoutConfig.MATCH_PARENT, LayoutConfig.MATCH_PARENT));
            relativeLayout.addComponent(mTabParentView);
            relativeLayout.addComponent(addScrollableLine());

            mAutoScrollHorizontalScrollView = new ScrollView(mContext);
            mAutoScrollHorizontalScrollView.setLayoutConfig(new LayoutConfig(LayoutConfig.MATCH_PARENT,
                    LayoutConfig.MATCH_PARENT));
            mAutoScrollHorizontalScrollView.setEnabled(true);

            DirectionalLayout linearLayout = new DirectionalLayout(mContext);
            linearLayout.setLayoutConfig(new DirectionalLayout.LayoutConfig(LayoutConfig.MATCH_CONTENT,
                    LayoutConfig.MATCH_CONTENT));
            linearLayout.setOrientation(Component.VERTICAL);
            linearLayout.addComponent(relativeLayout);

            mAutoScrollHorizontalScrollView.addComponent(linearLayout);

            addComponent(mAutoScrollHorizontalScrollView);
        } else {
            addComponent(mTabParentView);
            addComponent(addScrollableLine());
        }
        mViewPager.addPageChangedListener(this);
        invalidate();
    }

    private void updateIndicator(boolean isUpdateScrollLine) {
        if (mViewPager == null || mViewPager.getProvider() == null) {
            return;
        }
        PageSliderProvider pagerAdapter = mViewPager.getProvider();
        int pageCount = pagerAdapter.getCount();
        if (mTabParentView == null) {
            mTabParentView = createTabParentView();
        }
        int oldCount = mTabParentView.getChildCount();
        if (oldCount > pageCount) {
            mTabParentView.removeComponents(pageCount, oldCount - pageCount);
        }
        for (int index = 0; index < pageCount; index++) {
            boolean isOldChild = index < oldCount;
            Component childView;
            if (isOldChild) {
                childView = mTabParentView.getComponentAt(index);
            } else {
                childView = createTabView(pagerAdapter, index);
            }
            if (childView instanceof BasePagerTabView) {
                setTabTitleTextView(((BasePagerTabView) childView).getTabTextView(), index, pagerAdapter);
                setTabViewLayoutParams((BasePagerTabView) childView, index);
            } else {
                throw new IllegalArgumentException("childView must be PageTabView");
            }
        }
        if (isUpdateScrollLine) {
            EventRunner eventRunner = EventRunner.create(false);
            EventHandler eventHandler = new EventHandler(eventRunner);

            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    onPageSliding(mViewPager.getCurrentPage(), 0, 0);
                    onPageChosen(mViewPager.getCurrentPage());
                }
            };
            eventHandler.postTask(runnable);
        }
    }

    private void transactionScrollTitleParentToCenter(int position) {
        final int positionLeft = mTabParentView.getComponentAt(position).getLeft();
        final int positionWidth = mTabParentView.getComponentAt(position).getWidth();
        final int halfScreenWidth = (TabUtils.getScreenPixWidth(mContext) - getPaddingLeft()
                - getPaddingRight()) / (int) VALUE_TWO;
        if (mAutoScrollHorizontalScrollView != null) {
            mAutoScrollHorizontalScrollView.fluentScrollTo(positionLeft + positionWidth / (int) VALUE_TWO
                    - halfScreenWidth, 0);
        }
    }

    private void linkageScrollTitleParentToCenter(int position, float positionOffset) {
        if (mTabParentView != null && position < mTabParentView.getChildCount()) {
            Component positionView = mTabParentView.getComponentAt(position);
            int positionRight = 0;
            int positionWidth = 0;
            if (positionView != null) {
                positionRight = positionView.getRight();
                positionWidth = positionView.getWidth();
            }
            Component afterView = mTabParentView.getComponentAt(position + 1);

            int afterViewWidth = 0;
            if (afterView != null) {
                afterViewWidth = afterView.getWidth();
            }
            final int halfScreenWidth = (TabUtils.getScreenPixWidth(mContext)
                    - getPaddingLeft() - getPaddingRight()) / (int) VALUE_TWO;
            int offsetStart = positionRight - positionWidth / (int) VALUE_TWO - halfScreenWidth;
            int scrollX = (int) ((afterViewWidth / VALUE_TWO + positionWidth / VALUE_TWO) * positionOffset)
                    + offsetStart;
            if (mAutoScrollHorizontalScrollView != null) {
                mAutoScrollHorizontalScrollView.fluentScrollTo(scrollX, 0);
            }
        }
    }

    private void updateTitleStyle(int position) {
        if (mTabParentView == null) {
            return;
        }
        for (int index = 0; index < mTabParentView.getChildCount(); index++) {
            Component childView = mTabParentView.getComponentAt(index);
            if (childView instanceof BasePagerTabView) {
                Text textView = ((BasePagerTabView) childView).getTabTextView();
                if (textView == null) {
                    continue;
                }
                if (position == index) {
                    textView.setTextColor(new Color(mTabSelectedTextColor));
                    textView.setFont(isTabSelectedTextBold ? Font.DEFAULT_BOLD : Font.DEFAULT);
                    textView.setTextSize((int) mTabSelectedTextSize);
                } else {
                    textView.setTextColor(new Color(mTabNormalTextColor));
                    textView.setFont(isTabNormalTextBold ? Font.DEFAULT_BOLD : Font.DEFAULT);
                    textView.setTextSize((int) mTabNormalTextSize);
                }
            }
        }
    }

    private ScrollableLine addScrollableLine() {
        int firstItemWidth = calculateFirstItemWidth();
        mScrollableLine = new ScrollableLine(mContext, firstItemWidth / VALUE_TWO - DEFAULT_LINE_WIDTH,
                firstItemWidth / VALUE_TWO + DEFAULT_LINE_WIDTH);
        calculateIndicatorLineWidth();
        LayoutConfig scrollableLineParams = new LayoutConfig();
        scrollableLineParams.height = mIndicatorLineHeight;
        scrollableLineParams.setMarginTop(mIndicatorLineMarginTop);
        scrollableLineParams.setMarginBottom(mIndicatorLineMarginBottom);
        scrollableLineParams.addRule(LayoutConfig.ALIGN_PARENT_BOTTOM);
        mScrollableLine.setLayoutConfig(scrollableLineParams);
        mScrollableLine.setIndicatorLineRadius(mIndicatorLineRadius).setIndicatorLineHeight(mIndicatorLineHeight);
        return mScrollableLine;
    }

    private int calculateFirstItemWidth() {
        Component view = mTabParentView.getComponentAt(0);
        Text textView = ((BasePagerTabView) view).getTabTextView();
        if (textView instanceof Text) {
            float textWidth = calculateTextWidth(textView.getText().toString());
            return (int) (textWidth + VALUE_TWO * mTabPadding);
        }
        return 0;
    }

    private int calculateTextWidth(String text) {
        Paint textPaint = new Paint();
        textPaint.setTextSize((int) mTabSelectedTextSize);
        return (int) textPaint.measureText(text);
    }

    private void calculateIndicatorLineWidth() {
        if (mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE
                || mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE_CENTER) {
            if (mIndicatorLineWidth == 0) {
                mIndicatorLineWidth = calculateFirstItemWidth();
            }
        } else {
            if (mIndicatorLineWidth == 0) {
                mIndicatorLineWidth = TabUtils.getScreenPixWidth(mContext) / mTabParentView.getChildCount();
            }
        }
    }

    private DirectionalLayout createTabParentView() {
        DirectionalLayout linearLayout = new DirectionalLayout(mContext);
        LayoutConfig layoutParams = new LayoutConfig(
                (mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE_CENTER || mPagerIndicatorMode == INDICATOR_MODE_FIXED)
                        ? LayoutConfig.MATCH_PARENT : LayoutConfig.MATCH_CONTENT,
                LayoutConfig.MATCH_PARENT);
        linearLayout.setAlignment(mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE_CENTER ? LayoutAlignment.CENTER
                : LayoutAlignment.VERTICAL_CENTER);
        linearLayout.setLayoutConfig(layoutParams);
        linearLayout.setOrientation(DependentLayout.HORIZONTAL);
        return linearLayout;
    }

    private void setTabTitleTextView(Text textView, int position, PageSliderProvider pagerAdapter) {
        if (position == mViewPager.getCurrentPage()) {
            textView.setTextSize((int) mTabSelectedTextSize);
            textView.setTextColor(new Color(mTabSelectedTextColor));
        } else {
            textView.setTextSize((int) mTabNormalTextSize);
            textView.setTextColor(new Color(mTabNormalTextColor));
        }
        textView.setTextAlignment(TextAlignment.CENTER);
        String title = (String) pagerAdapter.getPageTitle(position);
        textView.setText(title);
    }

    private void setTabViewLayoutParams(BasePagerTabView basePagerTabView, final int position) {
        DirectionalLayout.LayoutConfig layoutParams;
        if (mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE
                || mPagerIndicatorMode == INDICATOR_MODE_SCROLLABLE_CENTER) {
            layoutParams = new DirectionalLayout.LayoutConfig(LayoutConfig.MATCH_CONTENT, LayoutConfig.MATCH_PARENT);
        } else {
            layoutParams = new DirectionalLayout.LayoutConfig(0, LayoutConfig.MATCH_PARENT, LayoutAlignment.CENTER,
                    1.0f);
        }
        layoutParams.alignment = LayoutAlignment.CENTER;
        basePagerTabView.setLayoutConfig(layoutParams);
        basePagerTabView.setPadding(mTabPadding, mTabPaddingTop, mTabPadding, mTabPaddingBottom);
        if (basePagerTabView.getComponentParent() == null) {
            mTabParentView.addComponent(basePagerTabView);
        }
        basePagerTabView.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (mViewPager != null) {
                    mViewPager.setCurrentPage(position);
                }
            }
        });

        basePagerTabView.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                switch (touchEvent.getAction()) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        ShapeElement shapeElement = new ShapeElement(getContext(), ResourceTable.Graphic_item_click);
                        shapeElement.setShape(ShapeElement.RECTANGLE);
                        basePagerTabView.setBackground(shapeElement);
                        break;
                    case TouchEvent.PRIMARY_POINT_UP:
                        ShapeElement shapeElement1 = new ShapeElement(getContext(), ResourceTable.Graphic_item_default);
                        shapeElement1.setShape(ShapeElement.RECTANGLE);
                        basePagerTabView.setBackground(shapeElement1);
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    /**
     * 创建tab view
     *
     * @param pagerAdapter pagerAdapter
     * @param position position
     * @return tab view
     */
    public BasePagerTabView createTabView(PageSliderProvider pagerAdapter, final int position) {
        return new PagerTabView(mContext);
    }
}